vimfandomcom-20200223-history
Making a list of numbers
This tip presents different methods showing how to insert a list of increasing numbers. Making a list It is easy to insert a list of ascending numbers, for example, this command inserts five lines after the current line: :put =range(11,15) The five lines are: 11 12 13 14 15 If wanted, the lines can be inserted after a particular line number, for example :123put =range(11,15) inserts them after line number 123, while :0put =range(11,15) inserts the lines at the start of the buffer, and :$put =range(11,15) inserts them after the last line. An equivalent command is :call append(123,range(11,15))) to insert the five lines after line number 123, for example. The list of numbers can be formatted. For example, the following inserts 150 lines, where each line contains a number displayed in four columns with leading zeros. :put =map(range(1,150), 'printf(%04d, v:val)') The results range from 0001 to 0150. The map() function replaces each value with the result of the expression, which must be given as a string (the double '' presents a single apostrophe when inside an apostrophe-quoted string). In the expression, v:val represents each value from the list in the first argument. Here is another example, using a loop rather than map(): :for i in range(1,10) | put ='192.168.0.'.i | endfor Executing this command inserts the following after the current line: 192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.4 192.168.0.5 192.168.0.6 192.168.0.7 192.168.0.8 192.168.0.9 192.168.0.10 Substitute with ascending numbers Suppose you want to replace each occurrence of "abc" with "xyz_N" where N is an ascending number (xyz_1, xyz_2, xyz_3, and so on). One approach uses the following command: :let i=1 | g/abc/s//\='xyz_'.i/ | let i=i+1 However, this only changes the first abc on each line. Adding the g flag for a global substitute does not help as i is only incremented once per matching line. The following trick uses the a register which can be changed with the setreg() function: :let @a=1 | %s/abc/\='xyz_'.(@a+setreg('a',@a+1))/g As setreg returns 0 rather than a useful value, the replacement expression (\=) calls setreg by adding it to register a. Using a function Put the following script in your vimrc or in a file in your plugin directory. " Add argument (can be negative, default 1) to global variable i. " Return value of i before the change. function Inc(...) let result = g:i let g:i += a:0 > 0 ? a:1 : 1 return result endfunction Suppose you want to replace each occurrence of "abc" with "xyz_N" where N is an ascending number (xyz_1, xyz_2, xyz_3, and so on). To do this, enter the command: :let i = 1 | %s/abc/\='xyz_' . Inc()/g For another example, the following command replaces each occurrence of "abc" with a number that increases by 5, starting at 100 (the numbers will be 100, 105, 110, and so on): :let i=100 | :%s/abc/\=Inc(5)/g Incrementing selected numbers In Vim 8, the first number in a selection can be incremented by pressing Ctrl-A. If the selection covers several lines, the first number in the selection on each line is incremented. Alternatively, numbers in a selection covering several lines can be converted to a sequence by typing g Ctrl-A. For example, start with the following line: my_array0 = 0; Then copy it using Y6p (copy the line and paste it six times). The result is: my_array0 = 0; my_array0 = 0; my_array0 = 0; my_array0 = 0; my_array0 = 0; my_array0 = 0; my_array0 = 0; With the cursor on the first 0 in the first line, start a blockwise select by pressing Ctrl-V (or Ctrl-Q if you use Ctrl-V for pasting). Move the cursor down to select the first column of zeros, then press g Ctrl-A. Using Vim 8, that will give: my_array1 = 0; my_array2 = 0; my_array3 = 0; my_array4 = 0; my_array5 = 0; my_array6 = 0; my_array7 = 0; Vim 7 and earlier need a script or a macro to create a sequence. See also *Increasing or decreasing numbers *Generating a column of increasing numbers * * * * use Ctrl-A and Ctrl-X to operate on a visual selection Comments